package com.service.business.merchant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.service.business.base.dto.LoginUserSession;
import com.service.business.base.service.ConfigService;
import com.service.business.member.service.MemberService;
import com.service.business.merchant.controller.rep.MerchantPageRep;
import com.service.business.merchant.controller.rep.MerchantRep;
import com.service.business.merchant.controller.rep.MerchantSelfRep;
import com.service.business.merchant.controller.req.MerchantEnterReq;
import com.service.business.merchant.controller.req.MerchantPageReq;
import com.service.business.merchant.controller.req.MerchantUpdateReq;
import com.service.business.merchant.service.MerchantAuditRecordService;
import com.service.business.merchant.service.MerchantCreditLineService;
import com.service.business.merchant.service.MerchantService;
import com.service.business.support.SessionUtil;
import com.service.core.exception.CommonException;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.constants.ConfigConstants;
import com.service.dao.enums.CommonStatusEnums;
import com.service.dao.enums.MerchantCommodityEnum;
import com.service.dao.enums.MerchantEnums;
import com.service.dao.model.*;
import com.service.utility.common.UUIDUtil;
import com.service.utility.modelmapper.ModelMapperUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.service.dao.mapper.MerchantMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.stream.Collectors;


@Service("merchantService")
public class MerchantServiceImpl extends ServiceImpl<MerchantMapper, Merchant> implements MerchantService {

    @Autowired
    private SessionUtil sessionUtil;
    @Autowired
    private ConfigService configService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MerchantCreditLineService creditLineService;
    @Autowired
    private MerchantAuditRecordService auditRecordService;

    @Value("${merchantPrefix}")
    private String merchantPrefix;

    @Override
    public CommonPageRep<MerchantPageRep> page(MerchantPageReq pageReq) {

        Page<Merchant> page = PageHelper.startPage(pageReq.getPageNo(), pageReq.getPageSize());
        LoginUserSession session = sessionUtil.getUser();
        LambdaQueryWrapper<Merchant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Merchant::getMerchantStatus, MerchantEnums.Status.in_business.getCode());
        queryWrapper.ne(Merchant::getMemberId, session.getUserId());
        if (StringUtils.isNotBlank(pageReq.getKeyWord())) {
            queryWrapper.like(Merchant::getMerchantName, pageReq.getKeyWord())
                    .like(Merchant::getMerchantDesc, pageReq.getKeyWord());
        }
        list(queryWrapper);

        return CommonPageRep.buildResultRep(page, page.getResult().stream().map(item -> {
            MerchantPageRep result = ModelMapperUtil.map(item, MerchantPageRep.class);
            result.setAddress(item.getCity() + item.getCounty() + item.getAddress());
            return result;
        }).collect(Collectors.toList()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyEnter(MerchantEnterReq enterReq) {
        LoginUserSession session = sessionUtil.getUser();

        if (!ObjectUtils.isEmpty(getByMemberId(session.getUserId()))) {
            throw new CommonException("您已申请入驻,切勿重复申请", "merchant_exception_has_entered");
        }

        Date currentDate = new Date();
        Merchant merchant = ModelMapperUtil.map(enterReq, Merchant.class);
        merchant.setMerchantNo(buildMerchantNo());
        merchant.setCreateTime(currentDate);
        merchant.setMemberId(session.getUserId());
        save(merchant);
        SysConfig config = configService.getConfigByName(ConfigConstants.MERCHANT_CREDIT_LINE_COINS);

        if (ObjectUtils.isEmpty(config) || StringUtils.isBlank(config.getConfValue())) {
            log.error("商机额度货币未配置");
            return;
        }

        creditLineService.save(MerchantCreditLine.builder()
                .coinsId(Integer.parseInt(config.getConfValue()))
                .coinsName(config.getConfOptions())
                .merchantId(merchant.getId())
                .memberId(merchant.getMemberId())
                .creditNum(BigDecimal.ZERO)
                .residueNum(BigDecimal.ZERO)
                .createTime(currentDate)
                .build());

        memberService.updateById(Member.builder()
                .id(session.getUserId())
                .merchant(CommonStatusEnums.ACTIVE.getCode())
                .build());
    }

    public String buildMerchantNo() {
        String no = merchantPrefix + DateFormatUtils.format(new Date(), "yyyyMMdd") + UUIDUtil.randomUUID10().substring(0, 8);
        Merchant merchant = getByMerchantNo(no);
        if (!ObjectUtils.isEmpty(merchant)) {
            no = buildMerchantNo();
        }
        return no;
    }

    @Override
    public MerchantSelfRep detail() {
        LoginUserSession session = sessionUtil.getUser();
        Merchant merchant = getByMemberId(session.getUserId());
        if (ObjectUtils.isEmpty(merchant)) {
            throw new CommonException("还未申请商检入驻", "merchant_exception_not_apply_enter");
        }

        MerchantSelfRep result = ModelMapperUtil.map(merchant, MerchantSelfRep.class);
        if (ObjectUtils.nullSafeEquals(result.getMerchantStatus(), MerchantEnums.Status.invalid.getCode())) {
            MerchantAuditRecord auditRecord = auditRecordService.getLastAudit(merchant.getId());
            result.setAuditStatus(auditRecord.getAuditStatus());
            result.setAuditMsg(auditRecord.getAuditMsg());
        }

        return result;
    }

    @Override
    public void update(MerchantUpdateReq updateReq) {
        LoginUserSession session = sessionUtil.getUser();

        Merchant merchant = getByMemberId(session.getUserId());
        if (ObjectUtils.isEmpty(merchant)) {
            throw new CommonException("还未申请商检入驻", "merchant_exception_not_apply_enter");
        }
        Integer merchantId = merchant.getId();
        Integer userStatus = merchant.getMerchantStatus();
        if (ObjectUtils.nullSafeEquals(merchant.getMerchantStatus(), MerchantEnums.Status.invalid.getCode())) {
            userStatus = MerchantEnums.Status.created.getCode();
        }
        merchant = ModelMapperUtil.map(updateReq, Merchant.class);
        merchant.setId(merchantId);
        merchant.setMerchantStatus(userStatus);

        updateById(merchant);

    }

    @Override
    public MerchantRep detail(String merchantNo) {
        Merchant merchant = getByMerchantNo(merchantNo);
        if (ObjectUtils.isEmpty(merchant)) {
            throw new CommonException("还未申请商检入驻", "merchant_exception_not_apply_enter");
        }
        return ModelMapperUtil.map(merchant, MerchantRep.class);
    }

    @Override
    public Merchant getByMemberId(Integer memberId) {
        return getOne(new QueryWrapper<Merchant>().lambda()
                .eq(Merchant::getMemberId, memberId).last(" limit 1"));
    }

    @Override
    public Merchant getByMemberIdAndStatus(Integer memberId) {
        return checkMerchantStatus(getOne(new QueryWrapper<Merchant>().lambda()
                .eq(Merchant::getMemberId, memberId)
                .in(Merchant::getMerchantStatus, MerchantEnums.getMerchantValidStatus())
                .last(" limit 1")));
    }

    @Override
    public Merchant getByMerchantNo(String merchantNo) {
        return getOne(new QueryWrapper<Merchant>().lambda()
                .eq(Merchant::getMerchantNo, merchantNo).last(" limit 1"));
    }

    @Override
    public Merchant getByMerchantNoAndStatus(String merchantNo) {
        return checkMerchantStatus(getOne(new QueryWrapper<Merchant>().lambda()
                .eq(Merchant::getMerchantNo, merchantNo).last(" limit 1")
                .in(Merchant::getMerchantStatus, MerchantEnums.getMerchantValidStatus())));
    }

    private Merchant checkMerchantStatus(Merchant merchant) {
        if (ObjectUtils.isEmpty(merchant)) {
            throw new CommonException("暂未开通商家服务", "merchant_exception_not_service");
        }

        if (ObjectUtils.nullSafeEquals(merchant.getMerchantStatus(), MerchantEnums.Status.frost.getCode())) {
            throw new CommonException("该商家已被冻结", "merchant_exception_hast_frost");
        }

        if (ObjectUtils.nullSafeEquals(merchant.getMerchantStatus(), MerchantEnums.Status.created.getCode())) {
            throw new CommonException("该商家正在审核中", "merchant_exception_verify");
        }
        return merchant;
    }

}
